<!DOCTYPE html>
<html lang="zh">
<head>
  <!-- 元数据 -->
  <meta charset="utf-8">
  <link rel="icon" href="/blog/images/favicon.ico">
  <title>控制反转与依赖注入 | YongKJ</title>
  <meta name="author" content="yongkj" />
  <meta http-equiv="Cache-Control" content="no-transform" />
  <meta http-equiv="Cache-Control" content="no-siteapp" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="robots" content="index,follow" />
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
  <meta name="format-detection" content="telphone=no, email=no" />
  
    
      <meta name="description" itemprop="description" content="Pursue excellence and success will follow." />
    
  
  <meta name="description" content="依赖倒置原则 要了解控制反转( Inversion of Control ), 我觉得有必要先了解软件设计的一个重要思想：依赖倒置原则（Dependency Inversion Principle ）。   什么是依赖倒置原则？假设我们设计一辆汽车：先设计轮子，然后根据轮子大小设计底盘，接着根据底盘设计车身，最后根据车身设计好整个汽车。这里就出现了一个“依赖”关系：汽车依赖车身，车身依赖底盘，底盘">
<meta property="og:type" content="article">
<meta property="og:title" content="控制反转与依赖注入">
<meta property="og:url" content="https://yongkj.gitee.io/blog/2021/02/12/java-ioc-di/index.html">
<meta property="og:site_name" content="YongKJ">
<meta property="og:description" content="依赖倒置原则 要了解控制反转( Inversion of Control ), 我觉得有必要先了解软件设计的一个重要思想：依赖倒置原则（Dependency Inversion Principle ）。   什么是依赖倒置原则？假设我们设计一辆汽车：先设计轮子，然后根据轮子大小设计底盘，接着根据底盘设计车身，最后根据车身设计好整个汽车。这里就出现了一个“依赖”关系：汽车依赖车身，车身依赖底盘，底盘">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://yongkj.gitee.io/blog/2021/02/12/java-ioc-di/wallhaven-552042.jpg">
<meta property="article:published_time" content="2021-02-12T06:54:04.000Z">
<meta property="article:modified_time" content="2021-02-12T07:04:32.815Z">
<meta property="article:author" content="yongkj">
<meta property="article:tag" content="容器">
<meta property="article:tag" content="设计">
<meta property="article:tag" content="倒置">
<meta property="article:tag" content="控制">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://yongkj.gitee.io/blog/2021/02/12/java-ioc-di/wallhaven-552042.jpg">
<meta name="twitter:site" content="@Candiinya">
  <link rel="alternate" href="atom.xml" type="application/atom+xml">
  <!-- 站点验证相关 -->
  
    
    
    
  
  <!-- 样式表文件 -->
  <link rel="stylesheet" id="kratos-css" href="/blog/css/kratosr.min.css" type="text/css" media="all">
  <link rel="stylesheet" id="highlight-css" href="/blog/css/highlight.min.css" type="text/css" media="all">
  <link rel="stylesheet" id="fontawe-css" href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" type="text/css" media="all">
  <link rel="stylesheet" id="nprogress-css" href="https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.min.css" type="text/css" media="all">
  
  
  
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css">
  
  
    <link rel="stylesheet" id="darkmode-css" href="/blog/css/kr-dark.min.css" type="text/css" media="all">
  
  <!-- 不得不预先加载的一些JS文件 -->
  <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js"></script>
  
    <script src="https://cdn.jsdelivr.net/npm/qrcode_js@1.0.0/qrcode.min.js"></script>
  
  
<meta name="generator" content="Hexo 5.2.0"></head>


    <body class="custom-background">
        <div id="kratos-wrapper">
    <div id="kratos-page">
        <div id="kratos-header">
            <div class="nav-toggle"><a class="kratos-nav-toggle js-kratos-nav-toggle"><i></i></a></div>
            <header id="kratos-header-section">
                <div class="container">
                    <div class="nav-header">
                        <div class="color-logo"><a href="/blog/">YongKJ</a></div>
                        <nav id="kratos-menu-wrap">
                            <ul id="kratos-primary-menu" class="sf-menu">
                            
                            
                                <li><a href="/blog/"><i class="fa fa-home"></i>首页</a></li>
                            
                            
                            
                                <li><a href="/blog/archives/"><i class="fa fa-file"></i>档案馆</a></li>
                            
                            
                            
                                <li>
                                <a><i class="fa fa-link"></i>链接</a>
                                <ul class="sub-menu">
                                    
                                    
                                    
                                    
                                        <li><a target="_blank" rel="noopener" href="http://software.yongkj.cn/software/">软件俱乐部</a></li>
                                    
                                    
                                    
                                        <li><a target="_blank" rel="noopener" href="http://pocketyun.yongkj.cn/">袖珍网盘吧</a></li>
                                    
                                    
                                    
                                        <li><a target="_blank" rel="noopener" href="http://study.yongkj.cn/">英语随身学</a></li>
                                    
                                    
                                </ul>
                                </li>
                            
                            
                            
                                <li><a href="/blog/atom.xml"><i class="fa fa-rss"></i>RSS 订阅</a></li>
                            
                            
                            
                                <li><a href="/blog/about/"><i class="fa fa-paper-plane"></i>关于我</a></li>
                            
                            
                            </ul>
                        </nav>
                    </div>
                </div>
            </header>
        </div>
        <div class="kratos-start kratos-hero-2">
            <!-- <div class="kratos-overlay"></div> -->
            <div class="kratos-cover kratos-cover-2 text-center">
                <div class="desc desc2 animate-box">
                    <a href="/blog/"><h2>YongKJ</h2><br><span>勇往直前，永不言弃</span></a>
                </div>
            </div>
        </div>

        <div id="kratos-blog-post">
            <div class="container">
                    <div class="row">
                        
        <div id="main">
            <section class="col-md-8">
    <article>
        <div class="kratos-hentry kratos-post-inner clearfix">
            <header class="kratos-entry-header">
                <h1 class="kratos-entry-title text-center">控制反转与依赖注入</h1>
                
                <div class="kratos-post-meta text-center">
                    <span>
                        <i class="fa fa-calendar"></i> 2021-02-12
                        <i class="fa fa-folder"></i> 分类于 <a class="label-link" href="/blog/categories/Java%E5%AD%A6%E4%B9%A0/">Java学习</a>
                        <i class="fa fa-user"></i> 作者 yongkj
                        <i class="fa fa-edit"></i> 
                        
                        
                            ~3.62K
                        
                        字
                        
                    </span>
                </div>
            </header>
            <div class="kratos-post-content">
                
                    <div class="kratos-post-inner-toc">
                        <ol class="toc"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BE%9D%E8%B5%96%E5%80%92%E7%BD%AE%E5%8E%9F%E5%88%99"><span class="toc-number">1.</span> <span class="toc-text">依赖倒置原则</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E5%92%8C%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5"><span class="toc-number">2.</span> <span class="toc-text">控制反转和依赖注入</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E5%AE%B9%E5%99%A8"><span class="toc-number">3.</span> <span class="toc-text">控制反转容器</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%AD%A3%E4%BE%9D%E8%B5%96"><span class="toc-number">4.</span> <span class="toc-text">正依赖</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BE%9D%E8%B5%96%E5%8F%8D%E8%BD%AC"><span class="toc-number">5.</span> <span class="toc-text">依赖反转</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%80%8E%E4%B9%88%E7%AE%80%E5%8C%96%E6%9E%84%E9%80%A0%E4%BB%A3%E7%A0%81%EF%BC%9F"><span class="toc-number">6.</span> <span class="toc-text">怎么简化构造代码？</span></a></li></ol>
                    </div>
                
                <hr />
                <h3 id="依赖倒置原则"><a href="#依赖倒置原则" class="headerlink" title="依赖倒置原则"></a>依赖倒置原则</h3><blockquote>
<p>要了解<strong>控制反转( Inversion of Control )</strong>, 我觉得有必要先了解软件设计的一个重要思想：<strong>依赖倒置原则（Dependency Inversion Principle ）</strong>。</p>
</blockquote>
<ol>
<li><strong>什么是依赖倒置原则？</strong>假设我们设计一辆汽车：先设计轮子，然后根据轮子大小设计底盘，接着根据底盘设计车身，最后根据车身设计好整个汽车。这里就出现了一个“依赖”关系：汽车依赖车身，车身依赖底盘，底盘依赖轮子。</li>
</ol>
<p><img src="http://file.yongkj.cn/fileSystem/admin/My%20Learning%20Material/%E9%9D%A2%E8%AF%95%E8%B5%84%E6%96%99/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E4%B8%8E%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5/v2-c68248bb5d9b4d64d22600571e996446_720w.png"></p>
<blockquote>
<p>这样的设计看起来没问题，但是可维护性却很低。假设设计完工之后，上司却突然说根据市场需求的变动，要我们把车子的轮子设计都改大一码。这下我们就蛋疼了：因为我们是根据轮子的尺寸设计的底盘，轮子的尺寸一改，底盘的设计就得修改；同样因为我们是根据底盘设计的车身，那么车身也得改，同理汽车设计也得改——整个设计几乎都得改！</p>
</blockquote>
<ol start="2">
<li>我们现在换一种思路。我们先设计汽车的大概样子，然后根据汽车的样子来设计车身，根据车身来设计底盘，最后根据底盘来设计轮子。这时候，依赖关系就倒置过来了：轮子依赖底盘， 底盘依赖车身， 车身依赖汽车。</li>
</ol>
<p><img src="http://file.yongkj.cn/fileSystem/admin/My%20Learning%20Material/%E9%9D%A2%E8%AF%95%E8%B5%84%E6%96%99/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E4%B8%8E%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5/v2-e64bf72c5c04412f626b21753aa9e1a1_720w.png"></p>
<blockquote>
<p>这时候，上司再说要改动轮子的设计，我们就只需要改动轮子的设计，而不需要动底盘，车身，汽车的设计了。</p>
<p>这就是依赖倒置原则——把原本的高层建筑依赖底层建筑“倒置”过来，变成底层建筑依赖高层建筑。高层建筑决定需要什么，底层去实现这样的需求，但是高层并不用管底层是怎么实现的。这样就不会出现前面的“牵一发动全身”的情况。</p>
</blockquote>
<h3 id="控制反转和依赖注入"><a href="#控制反转和依赖注入" class="headerlink" title="控制反转和依赖注入"></a>控制反转和依赖注入</h3><blockquote>
<p><strong>控制反转（Inversion of Control）</strong> 就是依赖倒置原则的一种代码设计的思路。具体采用的方法就是所谓的<strong>依赖注入（Dependency Injection）</strong>。其实这些概念初次接触都会感到云里雾里的。说穿了，这几种概念的关系大概如下：</p>
</blockquote>
<p><img src="http://file.yongkj.cn/fileSystem/admin/My%20Learning%20Material/%E9%9D%A2%E8%AF%95%E8%B5%84%E6%96%99/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E4%B8%8E%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5/v2-ee924f8693cff51785ad6637ac5b21c1_720w.jpg"></p>
<ol>
<li>为了理解这几个概念，我们还是用上面汽车的例子。只不过这次换成代码。我们先定义四个Class，车，车身，底盘，轮胎。然后初始化这辆车，最后跑这辆车。代码结构如下：</li>
</ol>
<p><img src="http://file.yongkj.cn/fileSystem/admin/My%20Learning%20Material/%E9%9D%A2%E8%AF%95%E8%B5%84%E6%96%99/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E4%B8%8E%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5/v2-8ec294de7d0f9013788e3fb5c76069ef_720w.jpg"></p>
<blockquote>
<p>这样，就相当于上面第一个例子，上层建筑依赖下层建筑——每一个类的构造函数都直接调用了底层代码的构造函数。假设我们需要改动一下轮胎（Tire）类，把它的尺寸变成动态的，而不是一直都是30。我们需要这样改：</p>
</blockquote>
<p><img src="http://file.yongkj.cn/fileSystem/admin/My%20Learning%20Material/%E9%9D%A2%E8%AF%95%E8%B5%84%E6%96%99/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E4%B8%8E%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5/v2-64e8b19eeb70d9cf87c27fe4c5c0fc81_720w.png"></p>
<ol start="2">
<li>由于我们修改了轮胎的定义，为了让整个程序正常运行，我们需要做以下改动：</li>
</ol>
<p><img src="http://file.yongkj.cn/fileSystem/admin/My%20Learning%20Material/%E9%9D%A2%E8%AF%95%E8%B5%84%E6%96%99/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E4%B8%8E%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5/v2-82e0c12a1b26f7979ed9241e169affda_720w.jpg"></p>
<blockquote>
<p>由此我们可以看到，仅仅是为了修改轮胎的构造函数，这种设计却需要<strong>修改整个上层所有类的构造函数</strong>！在软件工程中，<strong>这样的设计几乎是不可维护的</strong>——在实际工程项目中，有的类可能会是几千个类的底层，如果每次修改这个类，我们都要修改所有以它作为依赖的类，那软件的维护成本就太高了。</p>
</blockquote>
<ol start="3">
<li>所以我们需要进行控制反转（IoC），及上层控制下层，而不是下层控制着上层。我们用依赖注入（Dependency Injection）这种方式来实现控制反转。<strong>所谓依赖注入，就是把底层类作为参数传入上层类，实现上层类对下层类的“控制</strong>”。这里我们用<strong>构造方法传递的依赖注入方式</strong>重新写车类的定义：</li>
</ol>
<p><img src="http://file.yongkj.cn/fileSystem/admin/My%20Learning%20Material/%E9%9D%A2%E8%AF%95%E8%B5%84%E6%96%99/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E4%B8%8E%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5/v2-c920a0540ce0651003a5326f6ef9891d_720w.jpg"></p>
<ol start="4">
<li>这里我们再把轮胎尺寸变成动态的，同样为了让整个系统顺利运行，我们需要做如下修改：</li>
</ol>
<p><img src="http://file.yongkj.cn/fileSystem/admin/My%20Learning%20Material/%E9%9D%A2%E8%AF%95%E8%B5%84%E6%96%99/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E4%B8%8E%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5/v2-99ad2cd809fcb86dd791ff7f65fb1779_720w.jpg"></p>
<blockquote>
<p>看到没？这里<strong>我只需要修改轮胎类就行了，不用修改其他任何上层类。</strong>这显然是更容易维护的代码。不仅如此，在实际的工程中，这种设计模式还有利于<strong>不同组的协同合作和单元测试：</strong>比如开发这四个类的分别是四个不同的组，那么只要定义好了接口，四个不同的组可以同时进行开发而不相互受限制；而对于单元测试，如果我们要写Car类的单元测试，就只需要Mock一下Framework类传入Car就行了，而不用把Framework, Bottom, Tire全部new一遍再来构造Car。</p>
</blockquote>
<ol start="5">
<li>这里我们是采用的<strong>构造函数传入</strong>的方式进行的依赖注入。其实还有另外两种方法：<strong>Setter传递</strong>和<strong>接口传递</strong>。这里就不多讲了，核心思路都是一样的，都是为了实现<strong>控制反转</strong>。</li>
</ol>
<p><img src="http://file.yongkj.cn/fileSystem/admin/My%20Learning%20Material/%E9%9D%A2%E8%AF%95%E8%B5%84%E6%96%99/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E4%B8%8E%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5/v2-861683acac47577c81f2b7493dd05649_720w.jpg"></p>
<h3 id="控制反转容器"><a href="#控制反转容器" class="headerlink" title="控制反转容器"></a>控制反转容器</h3><blockquote>
<p>看到这里你应该能理解什么控制反转和依赖注入了。那什么是**控制反转容器(IoC Container)**呢？其实上面的例子中，对车类进行初始化的那段代码发生的地方，就是控制反转容器。</p>
</blockquote>
<p><img src="http://file.yongkj.cn/fileSystem/admin/My%20Learning%20Material/%E9%9D%A2%E8%AF%95%E8%B5%84%E6%96%99/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E4%B8%8E%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5/v2-c845802f9187953ed576e0555f76da42_720w.jpg"></p>
<blockquote>
<p>显然你也应该观察到了，因为采用了依赖注入，在初始化的过程中就不可避免的会写大量的new。这里IoC容器就解决了这个问题。<strong>这个容器可以自动对你的代码进行初始化，你只需要维护一个Configuration（可以是xml可以是一段代码），而不用每次初始化一辆车都要亲手去写那一大段初始化的代码</strong>。这是引入IoC Container的第一个好处。</p>
</blockquote>
<ol>
<li>IoC Container的第二个好处是：<strong>我们在创建实例的时候不需要了解其中的细节。</strong>在上面的例子中，我们自己手动创建一个车instance时候，是从底层往上层new的：</li>
</ol>
<p><img src="http://file.yongkj.cn/fileSystem/admin/My%20Learning%20Material/%E9%9D%A2%E8%AF%95%E8%B5%84%E6%96%99/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E4%B8%8E%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5/v2-555b2be7d76e78511a6d6fed3304927f_720w.jpg"></p>
<blockquote>
<p>这个过程中，我们需要了解整个Car/Framework/Bottom/Tire类构造函数是怎么定义的，才能一步一步new/注入。</p>
</blockquote>
<ol start="2">
<li>而IoC Container在进行这个工作的时候是反过来的，它先从最上层开始往下找依赖关系，到达最底层之后再往上一步一步new（有点像深度优先遍历）：</li>
</ol>
<p><img src="http://file.yongkj.cn/fileSystem/admin/My%20Learning%20Material/%E9%9D%A2%E8%AF%95%E8%B5%84%E6%96%99/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E4%B8%8E%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5/v2-24a96669241e81439c636e83976ba152_720w.jpg"></p>
<ol start="3">
<li>这里IoC Container可以直接隐藏具体的创建实例的细节，在我们来看它就像一个工厂：</li>
</ol>
<p><img src="http://file.yongkj.cn/fileSystem/admin/My%20Learning%20Material/%E9%9D%A2%E8%AF%95%E8%B5%84%E6%96%99/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E4%B8%8E%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5/v2-5ca61395f37cef73c7bbe7808f9ea219_720w.jpg"></p>
<blockquote>
<p>我们就像是工厂的客户。我们只需要向工厂请求一个Car实例，然后它就给我们按照Config创建了一个Car实例。我们完全不用管这个Car实例是怎么一步一步被创建出来。</p>
<p>实际项目中，有的Service Class可能是十年前写的，有几百个类作为它的底层。假设我们新写的一个API需要实例化这个Service，我们总不可能回头去搞清楚这几百个类的构造函数吧？IoC Container的这个特性就很完美的解决了这类问题——<strong>因为这个架构要求你在写class的时候需要写相应的Config文件，所以你要初始化很久以前的Service类的时候，前人都已经写好了Config文件，你直接在需要用的地方注入这个Service就可以了</strong>。这大大增加了项目的可维护性且降低了开发难度。</p>
<p>作者：Mingqi<br>链接：<a target="_blank" rel="noopener" href="https://www.zhihu.com/question/23277575/answer/169698662">https://www.zhihu.com/question/23277575/answer/169698662</a><br>来源：知乎<br>著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。</p>
</blockquote>
<h3 id="正依赖"><a href="#正依赖" class="headerlink" title="正依赖"></a>正依赖</h3><blockquote>
<p>依赖反转，从字面理解就是把依赖倒过来了呗，那原来依赖正着的时候是啥样的呢？</p>
<p>正着的时候是上层建筑依赖下层建筑，依赖方式是在自己构造的时候把下层先构造好，比如<code>Bird</code>和<code>Wing</code>：</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Bird</span> </span>&#123;</span><br><span class="line">    Wing wing;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Bird</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        wing = <span class="keyword">new</span> Wing();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Wing</span> </span>&#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>Main方法：<code>Bird bird = new Bird();</code></p>
<p>这就是典型的上层依赖下层（为了更方便理解，可以直接把依赖理解为依赖构造函数），这样的坏处是如果下层的构造函数改了，增减了参数，那上层的构造函数也得加上类似的参数，那如果上层还有上层呢？就要一层一层加上去（如果这里不理解的话建议戳上面的链接看知乎原文，答主说的肥肠清晰）。唯一的好处是Main方法倒是很简洁。</p>
</blockquote>
<h3 id="依赖反转"><a href="#依赖反转" class="headerlink" title="依赖反转"></a>依赖反转</h3><blockquote>
<p>这里按照上面的理解<code>（为了更方便理解，可以直接把依赖理解为依赖构造函数）</code>叫做取消依赖更合适一些，就是上层不再依赖于下层的构造函数，怎么做到的？下层直接构造好，把整个下层当做参数传进来</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Bird</span> </span>&#123;</span><br><span class="line">    Wing wing;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Bird</span><span class="params">(Wing w)</span> </span>&#123;</span><br><span class="line">        wing = w;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Wing</span> </span>&#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>Main方法：<code>Wing wing = new Wing(); Bird bird = new Bird(wing);</code></p>
<p>这样做，如果Wing类构造函数加个参数，只需要改Main方法就行了，坏处是如果建筑层数很多的话，需要从低到高一个一个new，如果用到的地方很多，每次创建一个顶层对象都要这样那真的很麻烦</p>
</blockquote>
<h3 id="怎么简化构造代码？"><a href="#怎么简化构造代码？" class="headerlink" title="怎么简化构造代码？"></a>怎么简化构造代码？</h3><ol>
<li>就是把构造的代码封装起来呗，所有地方都调用封装好的方法创建顶层对象</li>
<li>Spring更高级一些，通过注解或配置文件的方式，你连一次都不用自己写，不用知道这个从底层要高层的链路，只需要通过注解或者xml告诉Spring这个类依赖的下层类是什么，下层类自然也有自己的依赖，Spring会自己一层一层地往下找，然后从最底层开始new，直到返回顶层建筑对象</li>
</ol>

            </div>
            
                <div class="kratos-copyright text-center clearfix">
                    <h5>本作品采用 <a rel="license nofollow" target="_blank" href="http://creativecommons.org/licenses/by-sa/4.0/">知识共享署名-相同方式共享 4.0 国际许可协议</a> 进行许可</h5>
                </div>
            
            <footer class="kratos-entry-footer clearfix">
                
                    <div class="post-like-donate text-center clearfix" id="post-like-donate">
                    
                    
                        <a class="share" href="javascript:;"><i class="fa fa-share-alt"></i> 分享</a>
                        <div class="share-wrap" style="display: none;">
    <div class="share-group">
        <a href="javascript:;" class="share-plain qq" onclick="share('qq');" rel="nofollow">
            <div class="icon-wrap">
                <i class="fa fa-qq"></i>
            </div>
        </a>
        <a href="javascript:;" class="share-plain qzone" onclick="share('qzone');" rel="nofollow">
            <div class="icon-wrap">
                <i class="fa fa-star"></i>
            </div>
        </a>
        <a href="javascript:;" class="share-plain weixin pop style-plain" rel="nofollow">
            <div class="icon-wrap">
                <i class="fa fa-weixin"></i>
            </div>
            <div class="share-int">
                <div class="qrcode" id="wechat-qr"></div>
                <p>打开微信“扫一扫”，打开网页后点击屏幕右上角分享按钮</p>
            </div>
        </a>
        <a href="javascript:;" class="share-plain weibo" onclick="share('weibo');" rel="nofollow">
            <div class="icon-wrap">
                <i class="fa fa-weibo"></i>
            </div>
        </a>
        <a href="javascript:;" class="share-plain facebook style-plain" onclick="share('facebook');" rel="nofollow">
            <div class="icon-wrap">
                <i class="fa fa-facebook"></i>
            </div>
        </a>
        <a href="javascript:;" class="share-plain twitter style-plain" onclick="share('twitter');" rel="nofollow">
            <div class="icon-wrap">
                <i class="fa fa-twitter"></i>
            </div>
        </a>
    </div>
    <script type="text/javascript">
        $(()=>{
            new QRCode("wechat-qr", {
                text: "https://yongkj.gitee.io/blog/2021/02/12/java-ioc-di/",
                width: 150,
                height: 150,
                correctLevel : QRCode.CorrectLevel.H
            });
        });
        function share(dest) {
            const qqBase        = "https://connect.qq.com/widget/shareqq/index.html?";
            const weiboBase     = "https://service.weibo.com/share/share.php?";
            const qzoneBase     = "https://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?";
            const facebookBase  = "https://www.facebook.com/sharer/sharer.php?";
            const twitterBase   = "https://twitter.com/intent/tweet?";
            const hostUrl       = "https://yongkj.gitee.io/blog/2021/02/12/java-ioc-di/";
            const title         = "「控制反转与依赖注入」";
            const excerpt       = `依赖倒置原则
要了解控制反转( Inversion of Control ), 我觉得有必要先了解软件设计的一个重要思想：依赖倒置原则（Dependency Inversion Principle ）。


什么是依赖倒置原则？假设我...`;
            let _URL;
            switch (dest) {
                case "qq"       : _URL = qqBase+"url="+hostUrl+"&title="+title+"&desc=&summary="+excerpt+"&site=cxpy";     break;
                case "weibo"    : _URL = weiboBase+"url="+hostUrl+"&title="+title+excerpt;                                 break;
                case "qzone"    : _URL = qzoneBase+"url="+hostUrl+"&title="+title+"&desc=&summary="+excerpt+"&site=cxpy";  break;
                case "facebook" : _URL = facebookBase+"u="+hostUrl;                                                        break;
                case "twitter"  : _URL = twitterBase+"text="+title+excerpt+"&url="+hostUrl;                                break;
            }
            window.open(_URL);
        };
    </script>
</div>
                    
                    </div>
                
                <div class="footer-tag clearfix">
                    <div class="pull-left">
                    <i class="fa fa-tags"></i>
                        <a class="tag-none-link" href="/blog/tags/%E5%80%92%E7%BD%AE/" rel="tag">倒置</a>, <a class="tag-none-link" href="/blog/tags/%E5%AE%B9%E5%99%A8/" rel="tag">容器</a>, <a class="tag-none-link" href="/blog/tags/%E6%8E%A7%E5%88%B6/" rel="tag">控制</a>, <a class="tag-none-link" href="/blog/tags/%E8%AE%BE%E8%AE%A1/" rel="tag">设计</a>
                    </div>
                    <div class="pull-date">
                    <span>最后编辑：2021-02-12</span>
                    </div>
                </div>
            </footer>
        </div>
        
            <nav class="navigation post-navigation clearfix" role="navigation">
                
                <div class="nav-previous clearfix">
                    <a title=" 输入输出流" href="/blog/2021/02/09/java-io-stream/">&lt; 上一篇</a>
                </div>
                
                
                <div class="nav-next clearfix">
                    <a title=" 构造器的注入与使用" href="/blog/2021/02/12/java-constructor/">下一篇 &gt;</a>
                </div>
                
            </nav>
        
        
    </article>
</section>
        </div>
                
            <section id="kratos-widget-area" class="col-md-4 hidden-xs hidden-sm">
                
                    <aside id="krw-about" class="widget widget-kratos-about clearfix">
    
    <div class="photo-background"></div>
    <div class="photo-wrapper clearfix">
        <div class="photo-wrapper-tip text-center">
            <img class="about-photo" src="/blog/images/avatar.webp" />
        </div>
    </div>
    <div class="textwidget">
        
            <ol class="toc"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BE%9D%E8%B5%96%E5%80%92%E7%BD%AE%E5%8E%9F%E5%88%99"><span class="toc-number">1.</span> <span class="toc-text">依赖倒置原则</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E5%92%8C%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5"><span class="toc-number">2.</span> <span class="toc-text">控制反转和依赖注入</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E5%AE%B9%E5%99%A8"><span class="toc-number">3.</span> <span class="toc-text">控制反转容器</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%AD%A3%E4%BE%9D%E8%B5%96"><span class="toc-number">4.</span> <span class="toc-text">正依赖</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BE%9D%E8%B5%96%E5%8F%8D%E8%BD%AC"><span class="toc-number">5.</span> <span class="toc-text">依赖反转</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%80%8E%E4%B9%88%E7%AE%80%E5%8C%96%E6%9E%84%E9%80%A0%E4%BB%A3%E7%A0%81%EF%BC%9F"><span class="toc-number">6.</span> <span class="toc-text">怎么简化构造代码？</span></a></li></ol>
        
    </div>
</aside>
                
                    <!-- Moved to about.ejs -->
                
                    
  <aside id="krw-categories" class="widget widget-categories clearfix">
    <h4 class="widget-title"><i class="fa fa-folder"></i>分类目录</h4>
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/blog/categories/Java%E5%AD%A6%E4%B9%A0/">Java学习</a><span class="category-list-count">16</span></li><li class="category-list-item"><a class="category-list-link" href="/blog/categories/%E7%AC%AC%E4%B8%80%E6%AC%A1/">第一次</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/blog/categories/%E8%8B%B1%E8%AF%AD%E5%AD%A6%E4%B9%A0/">英语学习</a><span class="category-list-count">8</span></li><li class="category-list-item"><a class="category-list-link" href="/blog/categories/%E9%9F%B3%E4%B9%90%E7%A9%BA%E9%97%B4/">音乐空间</a><span class="category-list-count">3</span></li><li class="category-list-item"><a class="category-list-link" href="/blog/categories/%E9%A1%B9%E7%9B%AE%E7%BB%8F%E5%8E%86/">项目经历</a><span class="category-list-count">3</span></li></ul>
  </aside>


                
                    
  <aside id="krw-tags" class="widget widget-kratos-tags clearfix">
    <h4 class="widget-title"><i class="fa fa-tags"></i>标签聚合</h4>
      <div class="tag-clouds">
        <a href="/blog/tags/apility/" style="font-size: 0.6em;">apility</a> <a href="/blog/tags/bus/" style="font-size: 0.6em;">bus</a> <a href="/blog/tags/city/" style="font-size: 0.6em;">city</a> <a href="/blog/tags/comfort/" style="font-size: 0.6em;">comfort</a> <a href="/blog/tags/communication/" style="font-size: 0.6em;">communication</a> <a href="/blog/tags/contribute/" style="font-size: 0.6em;">contribute</a> <a href="/blog/tags/convenient/" style="font-size: 0.6em;">convenient</a> <a href="/blog/tags/develop/" style="font-size: 0.6em;">develop</a> <a href="/blog/tags/education/" style="font-size: 0.6em;">education</a> <a href="/blog/tags/enhance/" style="font-size: 0.6em;">enhance</a> <a href="/blog/tags/facility/" style="font-size: 0.6em;">facility</a> <a href="/blog/tags/flight/" style="font-size: 0.6em;">flight</a> <a href="/blog/tags/foreign/" style="font-size: 0.6em;">foreign</a> <a href="/blog/tags/free/" style="font-size: 0.6em;">free</a> <a href="/blog/tags/hello/" style="font-size: 0.6em;">hello</a> <a href="/blog/tags/improve/" style="font-size: 0.8em;">improve</a> <a href="/blog/tags/information/" style="font-size: 0.6em;">information</a> <a href="/blog/tags/invest/" style="font-size: 0.6em;">invest</a>
      </div>
  </aside>

                
                    
  <aside id="krw-posts" class="widget widget-kratos-poststab">
  <h4 class="widget-title"><i class="fa fa-file"></i>最新文章</h4>
  <div class="tab-content">
      <ul class="list-group">
        
        
          
          
            <a class="list-group-item" href="/blog/2021/02/12/java-dynamic-proxy/"><i class="fa  fa-book"></i> 动态代理</a>
            
          
        
          
          
            <a class="list-group-item" href="/blog/2021/02/12/java-constructor/"><i class="fa  fa-book"></i> 构造器的注入与使用</a>
            
          
        
          
          
            <a class="list-group-item" href="/blog/2021/02/12/java-ioc-di/"><i class="fa  fa-book"></i> 控制反转与依赖注入</a>
            
          
        
          
          
            <a class="list-group-item" href="/blog/2021/02/09/java-io-stream/"><i class="fa  fa-book"></i> 输入输出流</a>
            
          
        
          
          
            <a class="list-group-item" href="/blog/2021/02/08/java-class-loading/"><i class="fa  fa-book"></i> 类加载</a>
            
          
        
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
      </ul>
  </div>
  </aside>

                
            </section>
        
        </div>
    </div>
</div>
<footer>
    <div id="footer">
        <div class="kr-tool text-center">
            <div class="tool">
                
                    <div class="box search-box">
                        <a href="/blog/search/">
                            <span class="fa fa-search"></span>
                        </a>
                    </div>
                
                
                    <div class="box theme-box" id="darkmode-switch">
                        <span class="fa fa-adjust"></span>
                    </div>
                
                
            </div>
            <div class="box gotop-box">
                <span class="fa fa-chevron-up"></span>
            </div>
        </div>
        <div class="container">
            <div class="row">
                <div class="col-md-6 col-md-offset-3 footer-list text-center">
                    <ul class="kratos-social-icons">
                        
                        
                        <li><a target="_blank" rel="nofollow" href="https://t.me/CandyUnion"><i class="fa fa-telegram"></i></a></li>
                        <li><a target="_blank" rel="nofollow" href="https://twitter.com/Candiinya"><i class="fa fa-twitter"></i></a></li>
                        
                        
                        
                        <li><a target="_blank" rel="nofollow" href="https://github.com/yongkj"><i class="fa fa-github"></i></a></li>
                        <li><a target="_blank" rel="nofollow" href="/blog/atom.xml"><i class="fa fa-rss"></i></a></li>
                    </ul>
                    <ul class="kratos-copyright">
                        <div>
                            <li>&copy; 2021 yongkj 版权所有.</li>
                            <li>本站已运行<span id="span_dt">Loading...</span></li>
                        </div>
                        <div>
                            <li>Theme <a href="https://github.com/Candinya/Kratos-Rebirth" target="_blank">Kratos:Rebirth</a></li>
                            <li>Made with&nbsp;<i class="fa fa-heart throb" style="color:#d43f57"></i>&nbsp;by <a href="https://candinya.com" target="_blank" rel="nofollow">Candinya</a>.</li>
                        </div>
                        <div>
                            <li>Powered by <a href="https://hexo.io" target="_blank" rel="nofollow">Hexo</a></li>
                            <li>Hosted on <a href="https://www.yongkj.cn" target="_blank">勇往直前</a></li>
                        </div>
                        <div>
                            
                            
                        </div>
                    </ul>
                </div>
            </div>
        </div>
    </div>
</footer>
</div>
</div>

        <script defer src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.4/dist/js/bootstrap.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.js"></script>
<script>const notMobile = (!(navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)));</script>

    <div>
        <canvas id="snow"></canvas>
        <script async type="text/javascript" src="/blog/js/snow.min.js"></script>
    </div>

<script async src="/blog/js/candy.min.js"></script>


    <script defer src="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js"></script>

<script defer src="https://cdn.jsdelivr.net/npm/clipboard@2.0.6/dist/clipboard.min.js"></script>
<script defer src="/blog/js/kratosr.min.js"></script>
<script defer src="/blog/js/pjax.min.js"></script>


    <script defer src="/blog/js/kr-dark.min.js"></script>



    </body>
</html>